﻿using Enterprises.Wpf.Core.IO;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Enterprises.Wpf.Core
{
    /// <summary>
    /// 扩展方法
    /// </summary>
    public static partial class PrototypeHelper
    {
        /// <summary>
        /// 指定字符串是否为 null 或 System.String.Empty 字符串
        /// </summary>
        /// <param name="_">字符串</param>
        /// <returns>返回结果
        /// <para><term>true</term> 符合正则表达式</para>
        /// <para><term>false</term> 不符合正则表达式</para>
        /// </returns>
        public static Boolean IsNullOrEmpty(this String _)
        {
            if (_ != null) return _.Length == 0;
            return true;
        }

        public static Boolean IsNotNullOrEmpty(this String _) => !_.IsNullOrEmpty();

        /// <summary>
        /// 指定字符串是否为 null 或 System.String.Empty 字符串
        /// </summary>
        /// <param name="_">对象</param>
        /// <returns>返回结果
        /// <para><term>true</term> 符合正则表达式</para>
        /// <para><term>false</term> 不符合正则表达式</para>
        /// </returns>
        public static Boolean IsNullOrEmpty<T>(this T _)
        {
            if (_ == null) return true;
            var t = _.GetType();
            if (t == typeof(DBNull)) return true;
            if (t == typeof(String)) return _.ToString().IsNullOrEmpty();

            return false;
        }

        #region 不区分大小写的比较
        /// <summary>
        /// 不区分大小写的比较
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="val">原值</param>
        /// <param name="other">其它值</param>
        /// <returns></returns>
        public static bool EqualsIgnoreCase<T>(this T val, params T[] other)
        {
            if (val.IsNullOrEmpty())
            {
                foreach (var o in other)
                    if (o.IsNullOrEmpty()) return true;
                return false;
            }
            foreach (var o in other)
            {
                if (typeof(T) == typeof(String))
                {
                    if (val.ToString().Equals(o?.ToString(), StringComparison.OrdinalIgnoreCase)) return true;
                }
                else
                {
                    if (val.Equals(o)) return true;
                }
            }
            return false;
        }
        #endregion


        #region 循环遍历数据 ForEach
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="enumerable">类型对象</param>
        /// <param name="action">无返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable<T> Each<T>(this IEnumerable<T> enumerable, Action<T> action)
        {
            if (enumerable == null || action == null) return enumerable;
            foreach (T t in enumerable) action(t);
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="enumerable">类型对象</param>
        /// <param name="action">无返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable<T> Each<T>(this IEnumerable<T> enumerable, Action<T, int> action)
        {
            if (enumerable == null || enumerable.Count() == 0 || action == null) return enumerable;
            int i = 0;
            foreach (T t in enumerable) action(t, i++);
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="enumerable">类型对象</param>
        /// <param name="func">有返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable<T> Each<T>(this IEnumerable<T> enumerable, Func<T, Boolean> func)
        {
            if (enumerable == null || !enumerable.Any() || func == null) return enumerable;
            foreach (T t in enumerable) if (!func(t)) break;
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="enumerable">类型对象</param>
        /// <param name="func">有返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable<T> Each<T>(this IEnumerable<T> enumerable, Func<T, int, Boolean> func)
        {
            if (enumerable == null || !enumerable.Any() || func == null) return enumerable;
            int i = 0;
            foreach (T t in enumerable) if (!func(t, i++)) break;
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <param name="enumerable">对象</param>
        /// <param name="action">无返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable Each<T>(this IEnumerable enumerable, Action<T> action)
        {
            if (enumerable == null || action == null) return enumerable;
            foreach (T o in enumerable) action(o);
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <param name="enumerable">对象</param>
        /// <param name="action">无返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable Each<T>(this IEnumerable enumerable, Action<T, int> action)
        {
            if (enumerable == null || action == null) return enumerable;
            int i = 0;
            foreach (T o in enumerable) action(o, i++);
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <param name="enumerable">对象</param>
        /// <param name="func">有返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable Each<T>(this IEnumerable enumerable, Func<T, Boolean> func)
        {
            if (enumerable == null || func == null) return enumerable;
            foreach (T o in enumerable) if (!func(o)) break;
            return enumerable;
        }
        /// <summary>
        /// 循环遍历数据
        /// </summary>
        /// <param name="enumerable">对象</param>
        /// <param name="func">有返回值Lambda</param>
        /// <returns></returns>
        public static IEnumerable Each<T>(this IEnumerable enumerable, Func<T, int, Boolean> func)
        {
            if (enumerable == null || func == null) return enumerable;
            int i = 0;
            foreach (T o in enumerable) if (!func(o, i++)) break;
            return enumerable;
        }
        #endregion

        #region 字符串字节互转
        /// <summary>
        /// 获取字节编码
        /// </summary>
        /// <param name="_">字节</param>
        /// <returns>字节编码</returns>
        public static Encoding GetEncoding(this byte[] _) => FileHelper.GetEncoding(_);
        /// <summary>
        /// 将指定字符数组中的所有字符编码为一个字节序列
        /// </summary>
        /// <param name="chars">包含要编码的字符的字符数组</param>
        /// <param name="encoding">编码</param>
        /// <returns>一个字节数组，包含对指定的字符集进行编码的结果</returns>
        public static byte[] GetBytes(this char[] chars, Encoding encoding = null) => chars.Any() ? (encoding ?? Encoding.UTF8).GetBytes(chars) : Array.Empty<byte>();
        /// <summary>
        /// 字符串转字节组
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns>一个字节数组，包含对指定的字符集进行编码的结果</returns>
        public static byte[] GetBytes(this String _, Encoding encoding = null) => _.IsNullOrEmpty() ? Array.Empty<byte>() : (encoding ?? Encoding.UTF8).GetBytes(_);
        /// <summary>
        /// 字符串转字节
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns>一个字节数组，包含对指定的字符集进行编码的结果</returns>
        public static byte[] GetBytes(this String _, string encoding) => Encoding.GetEncoding(encoding ?? "UTF-8").GetBytes(_);
        /// <summary>
        /// 字符串转字节
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns>一个字节数组，包含对指定的字符集进行编码的结果</returns>
        public static sbyte[] GetSBytes(this String _, Encoding encoding = null)
        {
            var bytes = (encoding ?? Encoding.UTF8).GetBytes(_);
            var bs = new sbyte[bytes.Length];
            bytes.Each((b, index) =>
            {
                bs[index] = (sbyte)b;
            });
            return bs;
        }
        /// <summary>
        /// 字符串转字节
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns>一个字节数组，包含对指定的字符集进行编码的结果</returns>
        public static sbyte[] GetSBytes(this String _, string encoding) => _.GetSBytes(Encoding.GetEncoding(encoding));
        /// <summary>
        /// 字节转字符串
        /// </summary>
        /// <param name="_">字节</param>
        /// <param name="encoding">编码</param>
        /// <param name="index">开始位置</param>
        /// <param name="count">长度</param>
        /// <returns>包含指定字节序列解码结果的字符串</returns>
        public static string GetString(this byte[] _, Encoding encoding, int index = 0, int count = 0)
        {
            var result = string.Empty;
            if (_ == null || _.Length == 0) return result;
            var _encoding = encoding ?? _.GetEncoding();
            if (_encoding.WebName == Encoding.UTF8.WebName && _.Length >= 3 && _[0] == 0xEF && _[1] == 0xBB && _[2] == 0xBF)
                index = 3;
            result = _encoding.GetString(_, index, count == 0 ? _.Length - index : count + index > _.Length ? _.Length - index : count);
            return result;
        }
        /// <summary>
        /// 字节转字符串
        /// </summary>
        /// <param name="_">字节</param>
        /// <param name="encoding">编码</param>
        /// <param name="index">开始位置</param>
        /// <param name="count">长度</param>
        /// <returns>包含指定字节序列解码结果的字符串</returns>
        public static string GetString(this byte[] _, string encoding = "", int index = 0, int count = 0)
        {
            var result = string.Empty;
            if (_ == null || _.Length == 0) return result;
            var _encoding = encoding.IsNullOrEmpty() ? _.GetEncoding() : Encoding.GetEncoding(encoding);
            return _.GetString(_encoding, index, count);
        }
        /// <summary>
        /// 将指定字节数组中的字节序列解码为指定的字符数组。
        /// </summary>
        /// <param name="_">包含要解码的字节序列的字节数组</param>
        /// <param name="byteIndex">第一个要解码的字节的索引</param>
        /// <param name="length">要解码的字节数</param>
        /// <param name="chars">要用于包含所产生的字符集的字符数组</param>
        /// <param name="charIndex">开始写入所产生的字符集的索引位置</param>
        /// <param name="encoding">编码</param>
        /// <returns>写入 chars 的实际字符数。</returns>
        public static int GetChars(this byte[] _, int byteIndex, int length, char[] chars, int charIndex, Encoding encoding = null)
        {
            if (_.IsNullOrEmpty()) return 0;
#if NETSTANDARD2_0
            if (chars == null) chars = new char[_.Length];
#else
            chars ??= new char[_.Length];
#endif
            return (encoding ?? _.GetEncoding()).GetChars(_, byteIndex, length, chars, charIndex);
        }
        /// <summary>
        /// 将指定字节数组中的字节序列解码为指定的字符数组。
        /// </summary>
        /// <param name="_">包含要解码的字节序列的字节数组</param>
        /// <param name="encoding">编码 默认是UTF8</param>
        /// <returns>一个字节数组，包含对指定的字节序列进行解码的结果。</returns>
        public static char[] GetChars(this byte[] _, Encoding encoding = null) => _.IsNullOrEmpty() ? Array.Empty<char>() : (encoding ?? _.GetEncoding()).GetChars(_);
        #endregion

        #region 替换移除模式
        /// <summary>
        /// 在指定输入子字符串内，使用指定替换字符串替换与某个正则表达式模式匹配的字符串（其数目为指定的最大数目）。
        /// </summary>
        /// <param name="_">要搜索匹配项的字符串。</param>
        /// <param name="pattern">要匹配的正则表达式模式</param>
        /// <param name="replacement">替换字符串。</param>
        /// <param name="count">可进行替换的最大次数。</param>
        /// <param name="startIndex">输入字符串中开始执行搜索的字符位置。</param>
        /// <param name="options">模式选项</param>
        /// <returns>一个与输入字符串基本相同的新字符串，唯一的差别在于，其中的每个匹配字符串已被替换字符串代替。 如果正则表达式模式与当前实例不匹配，则此方法返回未更改的当前实例。</returns>
        public static string ReplacePattern(this string _, string pattern, string replacement, int count, int startIndex, RegexOptions options = RegexOptions.IgnoreCase)
        {
            if (_.IsNullOrEmpty() || pattern.IsNullOrEmpty()) return _;
            var regex = new Regex(pattern, options);
            return regex.Replace(_, replacement, count, startIndex);
        }
        /// <summary>
        /// 替换模式
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="pattern">要匹配的正则表达式模式。</param>
        /// <param name="replacement">替换字符串。</param>
        /// <param name="options">模式选项</param>
        /// <returns></returns>
        public static string ReplacePattern(this string _, string pattern, string replacement = "", RegexOptions options = RegexOptions.IgnoreCase)
        {
            if (_.IsNullOrEmpty() || pattern.IsNullOrEmpty()) return _;
            return Regex.Replace(_, pattern, replacement ?? "", options);
        }
        /// <summary>
        /// 在指定的输入子字符串内，使用 System.Text.RegularExpressions.MatchEvaluator 委托返回的字符串替换与某个正则表达式模式匹配的字符串（其数目为指定的最大数目）。
        /// </summary>
        /// <param name="_">要搜索匹配项的字符串。</param>
        /// <param name="pattern">要匹配的正则表达式模式。</param>
        /// <param name="m">一个自定义方法，该方法检查每个匹配项，然后返回原始的匹配字符串或替换字符串。</param>
        /// <param name="count">进行替换的最大次数。</param>
        /// <param name="startIndex">输入字符串中开始执行搜索的字符位置。</param>
        /// <param name="options">模式选项</param>
        /// <returns></returns>
        public static string ReplacePattern(this string _, string pattern, MatchEvaluator m, int count, int startIndex, RegexOptions options = RegexOptions.IgnoreCase)
        {
            if (_.IsNullOrEmpty() || pattern.IsNullOrEmpty()) return _;
            var regex = new Regex(pattern, options);
            return regex.Replace(_, m, count, startIndex);
        }
        /// <summary>
        /// 替换模式
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="pattern">要匹配的正则表达式模式。</param>
        /// <param name="m">方法操作过程中每当找到正则表达式匹配时都调用的方法</param>
        /// <param name="options">模式选项</param>
        /// <returns></returns>
        public static string ReplacePattern(this string _, string pattern, MatchEvaluator m, RegexOptions options = RegexOptions.IgnoreCase)
        {
            if (_.IsNullOrEmpty() || pattern.IsNullOrEmpty()) return _;
            return Regex.Replace(_, pattern, m, options);
        }
        /// <summary>
        /// 移除模式
        /// </summary>
        /// <param name="_">字符串</param>
        /// <param name="pattern">要匹配的正则表达式模式。</param>
        /// <param name="options">模式选项</param>
        /// <returns></returns>
        public static string RemovePattern(this string _, string pattern, RegexOptions options = RegexOptions.IgnoreCase)
        {
            return _.ReplacePattern(pattern, "", options);
        }
        #endregion

        #region 是否是物理路径
        /// <summary>
        /// 是否是物理路径 如果路径前边加{*}一定是物理路径
        /// </summary>
        /// <param name="_">字符串</param>
        /// <returns>返回结果
        /// <para><term>true</term> 符合正则表达式</para>
        /// <para><term>false</term> 不符合正则表达式</para>
        /// </returns>
        public static Boolean IsBasePath(this String _)
        {
            if (_.StartsWith("{*}")) return true;
            return _.StartsWith("/");
        }
        #endregion

        #region 赋值数组
        /// <summary>
        /// 赋值数组
        /// </summary>
        /// <param name="data">目标</param>
        /// <param name="destOffset">目标起始位置</param>
        /// <param name="source">源</param>
        /// <param name="sourceOffset">源开始</param>
        /// <param name="length">长度</param>
        /// <returns></returns>
        public static byte[] Write(this byte[] data, int destOffset, byte[] source, int sourceOffset = 0, int length = -1)
        {
            if (length == -1) length = source.Length - sourceOffset;
            if (data.IsNullOrEmpty()) data = new byte[destOffset + length];
            if (source.IsNullOrEmpty()) return data;
            if (source.Length <= sourceOffset + length) length = source.Length - sourceOffset;
            if (data.Length <= destOffset + length) length = data.Length - destOffset;
            Array.Copy(source, sourceOffset, data, destOffset, length);
            return data;
        }
        /// <summary>
        /// 赋值数组
        /// </summary>
        /// <param name="data">目标</param>
        /// <param name="source">源</param>
        /// <returns></returns>
        public static byte[] Write(this byte[] data, byte[] source) => data.Write(0, source);
        #endregion
    }
}
